//
//  WWNotificationCenter.m
//  ObjectCProject
//
//  Created by lvfeijun on 2022/12/8.
//

#import "WWNotificationCenter.h"
#import "WWObserverModel.h"

@interface WWNotificationCenter()
@property (nonatomic, strong) NSMutableDictionary *obsetvers;
@end

@implementation WWNotificationCenter

#pragma mark 注册监听者
+(WWNotificationCenter*)defaultCenter
{
    static WWNotificationCenter *singleton;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
        singleton =[[self alloc]initSingleton];
    });
    return singleton;
}

-(instancetype)initSingleton
{
    if([super init]){
        self.obsetvers =[[NSMutableDictionary alloc]init];
    }
    return self;
}

#pragma mark 注册观察者
-(void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSString*)aName object:(nullable id)anObject
{
    //如果不存在，那么即创建
    if(![self.obsetvers objectForKey:aName]){
        NSMutableArray *arrays =[[NSMutableArray alloc]init];
        //创建数组模型
        WWObserverModel *observerModel =[[WWObserverModel alloc]init];
        observerModel.observer = observer;
        observerModel.selector = aSelector;
        observerModel.notificationName = aName;
        observerModel.object = anObject;
        
        [arrays addObject:observerModel];
        //填充进入数组
        [self.obsetvers setObject:arrays forKey:aName];
        
    }else{
        //如果存在，取出来，继续添加减去即可
        NSMutableArray *arrays =(NSMutableArray*)[self.obsetvers objectForKey:aName];
        
        //创建数组模型
        WWObserverModel *observerModel =[[WWObserverModel alloc]init];
        observerModel.observer = observer;
        observerModel.selector = aSelector;
        observerModel.notificationName = aName;
        observerModel.object = anObject;
        [arrays addObject:observerModel];
    }
}

-(id )addObserverForName:(nullable NSString *)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void(^)(WWNotification *note))block
{
    //如果不存在，那么即创建
    if(![self.obsetvers objectForKey:name]){
        NSMutableArray *arrays =[[NSMutableArray alloc]init];
        
        //创建数组模型
        WWObserverModel *observerModel =[[WWObserverModel alloc]init];
        observerModel.block = block;
        observerModel.notificationName = name;
        observerModel.object = obj;
        observerModel.operationQueue = queue;

        [arrays addObject:observerModel];
        //填充进入数组
        [self.obsetvers setObject:arrays forKey:name];
        
    }else{
        //如果存在，取出来，继续添加即可
        NSMutableArray *arrays =(NSMutableArray*)[self.obsetvers objectForKey:name];

        //创建数组模型
        WWObserverModel *observerModel =[[WWObserverModel alloc]init];
        observerModel.block = block;
        observerModel.notificationName = name;
        observerModel.object = obj;
        observerModel.operationQueue = queue;
        
        [arrays addObject:observerModel];
    }
    return nil;
}

#pragma mark 发送消息
-(void)postNotification:(WWNotification *)notification
{
    //name取出来对应观察者数组，执行任务
    NSMutableArray *arrays =(NSMutableArray*)[self.obsetvers objectForKey:notification.name];
    [arrays enumerateObjectsUsingBlock:^(id  _Nonnull obj,NSUInteger idx,BOOL * _Nonnull stop){
        //取出数据模型
        WWObserverModel *observerModel = obj;
        id observer = observerModel.observer;
        SEL secector = observerModel.selector;

        if(!observerModel.operationQueue){

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

            [observer performSelector:secector withObject:notification];
            
#pragma clang diagnostic pop

        }else{
            //创建任务
            NSBlockOperation *operation =[NSBlockOperation blockOperationWithBlock:^{
                //这里用block回调出去
                observerModel.block(notification);
            }];
            //如果添加观察者 传入 队列，那么就任务放在队列中执行(子线程异步执行)
            NSOperationQueue *operationQueue = observerModel.operationQueue;
            [operationQueue addOperation:operation];
        }
    }];
}

-(void)postNotificationName:(NSString *)aName object:(id)object userInfo:(NSDictionary *)userInfo
{
    
    //name取出来对应观察者数组，执行任务
    NSMutableArray *arrays =(NSMutableArray*)[self.obsetvers objectForKey:aName];
    for (WWObserverModel *observerModel in arrays) {
        //如果不是则继续
        if (![object isEqual:observerModel.observer]) {
            continue;
        }
        
        id observer = observerModel.observer;
        SEL secector = observerModel.selector;

        if(!observerModel.operationQueue){

#pragma clang diagnostic push

#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

            [observer performSelector:secector withObject:userInfo];
            
#pragma clang diagnostic pop

        }else{
            //创建任务
            NSBlockOperation *operation =[NSBlockOperation blockOperationWithBlock:^{
                //这里用block回调出去
                observerModel.block(nil);
            }];
            //如果添加观察者 传入 队列，那么就任务放在队列中执行(子线程异步执行)
            NSOperationQueue *operationQueue = observerModel.operationQueue;
            [operationQueue addOperation:operation];
        }
    };
}

-(void)postNotificationName:(NSString *)aName object:(id)object
{
    [self postNotificationName:aName object:object userInfo:nil];
}

#pragma mark 移除消息
-(void)removeObserver:(id)observer
{
    //name取出来对应观察者数组，执行任务
    NSArray *temp = self.obsetvers.allValues;
    for (NSMutableArray *arrays in temp) {
        for (WWObserverModel *observerModel in arrays) {
            //如果不是则继续
            if (![observer isEqual:observerModel.observer]) {
                continue;
            }else {
                [arrays removeObject:observerModel];
                break;
            }
        }
    }
}
-(void)removeObserver:(id)observer name:(NSString *)aName object:(id)object
{
    //name取出来对应观察者数组，执行任务
    NSMutableArray *arrays = [self.obsetvers objectForKey:aName];
    for (WWObserverModel *observerModel in arrays) {
        //如果不是则继续
        if (![observer isEqual:observerModel.observer]) {
            continue;
        }else {
            
            [arrays removeObject:observerModel];
            break;
        }
    }
}

@end
